/**
 * 组件中的方法
 */

import { ShapeFlags } from "@vue/shared";
import { PublicInstanceProxyHandlers } from "./componentPubliceInstance";

export function createComponentInstance(vnode) {
  const instance = { // 组件实例
    vnode,
    type: vnode.type, // 组件对象或者元素的字符串
    props: {}, // 组件里注册的属性
    attrs: {}, // attrs 排除组件里没有注册的属性
    slots: {},
    ctx: {},
    data: {c: 34},
    render: null,
    setupState: {b: 3}, // 如果 setup 返回对象作为 setupState
    isMounted: false, // 标识组件是否挂载
  }

  instance.ctx = {
    _: instance
  };

  return instance;
}

export function setupComponent(instance) {
  const { props, children } = instance.vnode;
  instance.props = props; // initProps()
  instance.children = children; // 包含插槽解析 initSlot()

  // 判断是否事有状态组件，函数组件

  let isStateful = instance.vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT;
  if (isStateful) { // 有状态组件
    // 调用当前实例的 setup 方法，用 setup 的返回值赋值给 setupState 和对应的 render 方法
    setupStatefulComponent(instance);
  }
}


function createSetupContext(instance) {
  return {
    attrs: instance.attrs,
    slots: instance.slots,
    emit: () => {},
    expose: () => {}
  }
}
function setupStatefulComponent(instance) {
  // 1. 代理，传递给 render 函数的参数
  instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers as any);
  // 2. 获取组件的类型，获取组件的 setup 方法
  const Component = instance.type;

  const { setup } = Component;

  const setupState = createSetupContext(instance);
  // 调用用户组件中的 setup 函数
  setup(instance.props, setupState);

  // 3. 调用 render 进行挂载渲染到页面
  Component.render(instance.proxy);
}